Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 17, 2025

Overview

This PR addresses critical command injection vulnerabilities identified by CodeQL code scanning alerts. The vulnerabilities existed in two locations where user-controllable input was concatenated into shell command strings without proper sanitization.

Security Issues Fixed

1. Command Injection in PackageManager

Location: packages/core/packages/PackageManager.ts

Vulnerability: Package names were directly concatenated into shell commands, allowing potential command injection attacks.

Before:

public static addPackage(packageName: string, verbose: boolean = false): boolean {
    const command = `npm install ${packageName} --quiet --save`;
    Util.execSync(command, { stdio: "pipe", encoding: "utf8" });
}

public static async queuePackage(packageName: string, verbose = false) {
    const command = `npm install ${packageName} --quiet --no-save`;
    exec(command, {}, callback);
}

After:

public static addPackage(packageName: string, verbose: boolean = false): boolean {
    const args = ['install', packageName, '--quiet', '--save'];
    Util.spawnSync('npm', args, { stdio: "pipe", encoding: "utf8" });
}

public static async queuePackage(packageName: string, verbose = false) {
    const args = ['install', packageName, '--quiet', '--no-save'];
    const child = spawn('npm', args);
    // ... handle stdout/stderr/close events
}

2. Command Injection in Start Command

Location: packages/cli/lib/commands/start.ts

Vulnerability: Port parameter was directly interpolated into a command string without validation.

Before:

const execSyncNpmStart = (port: number, options: ExecSyncOptions): void => {
    if (port) {
        Util.execSync(`npm start -- --port=${port}`, options);
        return;
    }
    Util.execSync(`npm start`, options);
};

After:

const execSyncNpmStart = (port: number, options: ExecSyncOptions): void => {
    const args = ['start'];
    if (port) {
        // Validate port is a number to prevent command injection
        if (!Number.isInteger(port) || port < 0 || port > 65535) {
            Util.error(`Invalid port number: ${port}`, "red");
            return;
        }
        args.push('--', `--port=${port}`);
    }
    Util.spawnSync('npm', args, options);
};

Why This Approach is Secure

The fix uses spawn/spawnSync with argument arrays instead of string concatenation. This approach:

  1. Prevents shell interpretation: Arguments are passed directly to the process without going through a shell
  2. Eliminates injection vectors: Special characters like ;, |, &, $() in user input are treated as literal strings, not shell metacharacters
  3. Adds validation: Port numbers are validated to be valid integers in the correct range (0-65535)

Testing

  • Updated all affected unit tests to match the new secure implementation
  • All existing tests continue to pass (298 passing, 8 pre-existing failures unrelated to these changes)
  • Added proper mocking for spawn and spawnSync in test suites
  • Verified optional chaining is properly transpiled to ES6-compatible code

Additional Changes

  • Added getInstallArgs() helper method to centralize argument array creation
  • Changed import from exec to spawn in PackageManager.ts
  • Updated test expectations to verify secure command construction

Breaking Changes

None. The public API remains unchanged; only the internal implementation has been updated to be more secure.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • www.google-analytics.com
    • Triggering command: Ignite UI CLI (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

chore: address code scanning alerts

The list of code scanning alerts is in the following list: https://github.com/IgniteUI/igniteui-cli/security/code-scanning

Note that this PR doesn't need to address dependabot alerts, which are already fixed in the following PR: @IgniteUI/igniteui-cli/pull/1437

Note that Dependabot


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix code scanning alerts in the project Fix command injection vulnerabilities in PackageManager and start command Oct 17, 2025
Copilot AI requested a review from Lipata October 17, 2025 06:52
@Lipata Lipata marked this pull request as ready for review October 17, 2025 06:54
@coveralls
Copy link

coveralls commented Oct 17, 2025

Coverage Status

coverage: 70.242% (-0.01%) from 70.252%
when pulling 492573f on copilot/address-code-scanning-alerts
into a23b067 on master.

@Lipata Lipata changed the title Fix command injection vulnerabilities in PackageManager and start command fix: command injection vulnerabilities in PackageManager and start command Oct 17, 2025
Hristo313
Hristo313 previously approved these changes Nov 5, 2025
@Lipata Lipata merged commit 1f86df3 into master Nov 5, 2025
4 checks passed
@Lipata Lipata deleted the copilot/address-code-scanning-alerts branch November 5, 2025 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants